package com.happy.qademo.websheet.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.util.UriComponentsBuilder;
import org.springframework.util.LinkedMultiValueMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.HttpStatusCodeException;
import org.springframework.web.client.RestTemplate;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import javax.servlet.http.HttpServletRequest;
import org.springframework.web.bind.annotation.CrossOrigin;

@CrossOrigin(origins = "*", allowedHeaders = "*")
@Controller
public class PanelController  { 

    private final RestTemplate restTemplate;

    @Autowired
    public PanelController(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }

    private final static Logger LOGGER = LoggerFactory.getLogger(PanelController.class);

    @Value("${server.port:9999}")
    int port;
  
    @Value("${spring.application.name:null}")
    String name;


    InetAddress address ; 
    {
        try {
            address = InetAddress.getLocalHost();
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
    }
    String host = address.getHostAddress();

    
    @GetMapping(value = {"", "/", "/mainIndex.html"})
    public String indexPage() {
        return "mainIndex";
    }

    
    @GetMapping(value = {"/debug.html", "/debug"})
    public String debugPage() {
        return "debug";
    }
    @GetMapping(value = {"/changeProject.html", "/changeProject"})
    public String changeProjectPage() {
        return "changeProject";
    }
    @GetMapping(value = {"/background.html", "/background"})
    public String backgroundPage() {
        return "background";
    }
    @GetMapping(value = {"/json.html", "/json"})
    public String jsonPage() {
        return "json";
    }
    @GetMapping(value = {"/env.html", "/env"})
    public String envPage() {
        return "env";
    }
    @GetMapping(value = {"/more.html", "/more"})
    public String morePage() {
        return "more";
    }
    @GetMapping(value = {"/setting.html", "/setting"})
    public String settingPage() {
        return "setting";
    }
    @GetMapping(value = {"/txcodeConfig.html", "/txcodeConfig"})
    public String txcodeConfigPage() {
        return "txcodeConfig";
    }
    @GetMapping(value = {"/ctoolindex.html", "/ctoolindex"})
    public String ctoolindexPage() {
        return "ctoolindex";
    }
    @GetMapping(value = {"/tool.html", "/tool"})
    public String ctoolPage() {
        return "tool";
    }
    @GetMapping(value = {"/mahuaindex.html", "/mahuaindex"})
    public String mahuaPage() {
        return "mahuaindex";
    }
    @ResponseBody
    @RequestMapping(value = {"/admin/init.do", "/index.do"})
    public String adminPage() {
        return "success";
    }


    @ResponseBody
    @RequestMapping(value = "/zhuanfa/**", method = {RequestMethod.GET, RequestMethod.POST, RequestMethod.PUT, RequestMethod.DELETE})
    public ResponseEntity<String> forwardRequest(
            @RequestBody(required = false) String body,
            @RequestParam(required = false) Map<String, String> queryParams,
            @RequestParam("ServiceUrl") String ServiceUrl,
            @RequestParam(value ="concurrency", defaultValue ="1") int concurrency,
            @RequestParam(value ="totalRequests", defaultValue ="1") int totalRequests,
            HttpServletRequest request) {
        // 确保 concurrency 不小于 1
        if (concurrency < 1) {
            concurrency = 1;
        }
        // 确保 totalRequests 不小于 1
        if (totalRequests < 1) {
            totalRequests = 1;
        }
    
        String requestPath = request.getRequestURI();
        String pathPart = requestPath.substring(requestPath.indexOf("/zhuanfa") + "/zhuanfa".length());
        ServiceUrl = "http://" + ServiceUrl;
        UriComponentsBuilder uriComponentsBuilder = UriComponentsBuilder.fromHttpUrl(ServiceUrl).path(pathPart);
    
        // 处理请求参数
        List<String> parameterkeysToRemove = new ArrayList<>();
        parameterkeysToRemove.add("ServiceUrl");
        parameterkeysToRemove.add("concurrency");
        parameterkeysToRemove.add("totalRequests");

        MultiValueMap<String, String> parameterMap = new LinkedMultiValueMap<>();
        Enumeration<String> parameterNames = request.getParameterNames();
        while (parameterNames.hasMoreElements()) {
            String paramName = parameterNames.nextElement(); 
            if (!parameterkeysToRemove.contains(paramName)){
                String[] paramValues = request.getParameterValues(paramName);
                for (String value : paramValues) {
                    parameterMap.add(paramName, value);
                }
            }
        }
        uriComponentsBuilder.queryParams(parameterMap);
    
    
        String requestUri = uriComponentsBuilder.build().toUriString();
    
        HttpHeaders headers = new HttpHeaders();
        Enumeration<String> headerNames = request.getHeaderNames();
    
        List<String> keysToRemove = new ArrayList<>();
        keysToRemove.add("origin");
        keysToRemove.add("sec-fetch-site");
        keysToRemove.add("sec-fetch-mode");
        keysToRemove.add("sec-fetch-dest");
        keysToRemove.add("sec-ch-ua");
        keysToRemove.add("sec-ch-ua-mobile");
        keysToRemove.add("sec-fetch-platform");
        keysToRemove.add("referer");
    
        while (headerNames.hasMoreElements()) {
            String headerName = headerNames.nextElement();
            if (!keysToRemove.contains(headerName)) {
                headers.add(headerName, request.getHeader(headerName));
            } 
            if ("Cookie".equalsIgnoreCase(headerName)) {
                String cookieValue = request.getHeader(headerName);
                List<String> newCookies = new ArrayList<>();
                StringTokenizer st = new StringTokenizer(cookieValue, ";");
                while (st.hasMoreTokens()) {
                    String token = st.nextToken();
                    if (!token.contains("XSRF-TOKEN=")) {
                        newCookies.add(token);
                    }
                }
                headers.set("Cookie", String.join(";", newCookies));
            }else if ("Host".equalsIgnoreCase(headerName)) {
                headers.set("Host", ServiceUrl.substring(7));
            }
        }

         // 去除 body 中的指定参数
         if (body != null) {
            body = removeParamsFromBody(body, parameterkeysToRemove);
        }

        // 去除 body 中与 URL 参数重复的参数
        if (body != null && !parameterMap.isEmpty()) {
            body = removeDuplicateParamsFromBody(body, parameterMap);
        }

    
        HttpEntity<String> entity = new HttpEntity<>(body, headers);
        LOGGER.info(String.format("发送请求:\n requestUrl: %s,HttpMethod: %s, headers :  %s, body:  %s ",requestUri,request.getMethod(),headers,body));
        if (concurrency == 1 && totalRequests == 1) {
            try {
            ResponseEntity<String> response = restTemplate.exchange(requestUri, HttpMethod.valueOf(request.getMethod()), entity, String.class);
            String responseBody = response.getBody();
            String responseInfo = String.format("返回响应:\n Status Code: %s, Headers: %s, Body: %s",
                    response.getStatusCode(), response.getHeaders(), responseBody.toString());
            LOGGER.info(responseInfo);   
            return response;
            } catch (HttpStatusCodeException ex) {
            ResponseEntity<String> result = null;
            result = ResponseEntity
                    .status(ex.getStatusCode().value())
                    .headers(ex.getResponseHeaders())
                    .contentType(ex.getResponseHeaders().getContentType())
                    .body(ex.getResponseBodyAsString());
                return result;
            } catch (Exception e) {
            // 处理其他异常
            LOGGER.error("请求发生未知异常", e);
            HttpHeaders errorHeaders = new HttpHeaders();
            errorHeaders.setContentType(MediaType.TEXT_PLAIN);
            return new ResponseEntity<>(e.getMessage(), errorHeaders, HttpStatus.INTERNAL_SERVER_ERROR);
            }
        } else {
            // 计算每个线程应该执行的请求次数
            int totalRequestCount = concurrency * totalRequests;
            ExecutorService executorService = Executors.newFixedThreadPool(concurrency);
            CompletionService<ResponseEntity<String>> completionService = new ExecutorCompletionService<>(executorService);
            final int[] nums = {1};
            final int finalConcurrency = concurrency;
            List<Callable<ResponseEntity<String>>> tasks = new ArrayList<>();
            for (int i = 0; i < finalConcurrency; i++) {
                tasks.add(() -> {
                    List<ResponseEntity<String>> threadResponseList = new ArrayList<>();
                    // 每个线程执行的请求次数
                    int threadRequestCount = totalRequestCount / finalConcurrency;
                    for (int j = 0; j < threadRequestCount; j++) {
                        
                        ResponseEntity<String> response = restTemplate.exchange(requestUri, HttpMethod.valueOf(request.getMethod()), entity, String.class);
                        if (response!= null) {
                            String responseBody = response.getBody();
                            if (responseBody!= null) {
                                // 对响应体进行操作，去除结尾的 \n
                                String modifiedBody = responseBody.trim(); 
                                 // 更新响应体，可以创建一个新的 ResponseEntity
                                response = new ResponseEntity<>(modifiedBody, response.getHeaders(), response.getStatusCode());
                            }
                        } 
                        threadResponseList.add(response);
                    }
                    StringBuilder threadResponseBuilder = new StringBuilder();
                    for (ResponseEntity<String> threadResponse : threadResponseList) {      
                        threadResponseBuilder.append("\"第"+nums[0]+"次请求\":").append("{\"响应状态码\":\""+ threadResponse.getStatusCode()+"\",\"响应内容\":"+threadResponse.getBody()+"}").append(",");        
                        nums[0] = nums[0]+1;
                    }
                    return new ResponseEntity<>(threadResponseBuilder.toString(), headers, HttpStatus.OK);
                });
            }
            tasks.forEach(completionService::submit);
            List<ResponseEntity<String>> responseList = new ArrayList<>();
            for (int i = 0; i < finalConcurrency; i++) {
                try {
                    Future<ResponseEntity<String>> future = completionService.poll(10, TimeUnit.SECONDS);
                    if (future!= null) {
                        ResponseEntity<String> response = future.get();
                        if (response!= null) {
                            responseList.add(response);
                        }
                    }
                } catch (Exception e) {
                    // 可以在这里进行更细致的异常处理，如记录日志等
                }
            }
            executorService.shutdown();
            StringBuilder responseBuilder = new StringBuilder();
            responseBuilder.append("{");
            for (ResponseEntity<String> res : responseList) {
                responseBuilder.append(res.getBody());
            }
            responseBuilder.append("}");
            String reslut =responseBuilder.toString();
            if (reslut.endsWith(",}")) {
                reslut = reslut.substring(0, reslut.length() - 2) + "}";
            }
            return ResponseEntity.ok(reslut);
        }
    }



      // 从 body 中移除指定参数
      private String removeParamsFromBody(String body, List<String> params) {
        // 尝试判断是否为 JSON 格式
        if (isJson(body)) {
            return removeParamsFromJson(body, params);
        } else {
            // 普通字符串处理，假设参数格式为 key=value&key2=value2
            StringBuilder result = new StringBuilder();
            String[] pairs = body.split("&");
            for (String pair : pairs) {
                String[] keyValue = pair.split("=", 2);
                if (keyValue.length == 2 && !params.contains(keyValue[0])) {
                    if (result.length() > 0) {
                        result.append("&");
                    }
                    result.append(pair);
                }
            }
            return result.toString();
        }
    }

    // 判断字符串是否为 JSON 格式
    private boolean isJson(String str) {
        str = str.trim();
        return (str.startsWith("{") && str.endsWith("}")) || (str.startsWith("[") && str.endsWith("]"));
    }

    // 从 JSON 中移除指定参数
    private String removeParamsFromJson(String json, List<String> params) {
        for (String param : params) {
            json = json.replaceAll("\"" + param + "\":\\s*[^,}]*[,]?", "");
            // 去除可能剩余的逗号
            json = json.replaceAll(",}", "}");
        }
        return json;
    }

    // 从 body 中移除与 URL 参数重复的参数
    private String removeDuplicateParamsFromBody(String body, MultiValueMap<String, String> parameterMap) {
        if (isJson(body)) {
            for (String paramName : parameterMap.keySet()) {
                body = body.replaceAll("\"" + paramName + "\":\\s*[^,}]*[,]?", "");
                // 去除可能剩余的逗号
                body = body.replaceAll(",}", "}");
            }
        } else {
            StringBuilder result = new StringBuilder();
            String[] pairs = body.split("&");
            for (String pair : pairs) {
                String[] keyValue = pair.split("=", 2);
                if (keyValue.length == 2 && !parameterMap.containsKey(keyValue[0])) {
                    if (result.length() > 0) {
                        result.append("&");
                    }
                    result.append(pair);
                }
            }
            body = result.toString();
        }
        return body;
    }

}
